package com.zc.angelica.config.sucurity.handler;

import cn.hutool.crypto.digest.BCrypt;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zc.angelica.config.sucurity.UserService;
import com.zc.angelica.config.sucurity.exceptions.LoginException;
import com.zc.angelica.entity.Account;
import com.zc.angelica.entity.AccountClient;
import com.zc.angelica.entity.LastingLogin;
import com.zc.angelica.entity.ResponseData;
import com.zc.angelica.service.AccountService;
import com.zc.angelica.service.LastingLoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class MyAuthenticationProvider  implements AuthenticationProvider  {



    @Autowired
    private UserService userService;

    @Autowired
    private AccountService accountService;

    @Value("${validateCode.enabled}")
    private Boolean enabledVerifyCode;

    @Value("${jwt.lasting-code}")
    private String lastingCode;

    @Autowired
    private LastingLoginService lastingLoginService;

//    public MyAuthenticationProvider(UserService userService, AccountService accountService, Boolean enabledVerifyCode, String lastingCode, LastingLoginService lastingLoginService) {
//        this.userService = userService;
//        this.accountService = accountService;
//        this.enabledVerifyCode = enabledVerifyCode;
//        this.lastingCode = lastingCode;
//        this.lastingLoginService = lastingLoginService;
//    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        HttpServletRequest request = (HttpServletRequest) authentication.getDetails();
        JSONObject login = loginInfo(request);

        if (login == null) {
            throw new LoginException("请求内容不能为空！");
        }
        //获取验证码
        String inputVerify = login.getString("verifyCode");
        //获取输入的用户名
        String username = login.getString("username");
        //获取输入的明文
        String rawPassword = login.getString("password");
        //获取平台code
        String clientCode = request.getHeader(lastingCode);

        if (enabledVerifyCode) {
            if (inputVerify == null) {
                throw new LoginException("验证码不能为空！");
            }
            String validateCode = (String) request.getSession().getAttribute("validateCode");
            if (!validateCode.toLowerCase().trim().equals(inputVerify.trim().toLowerCase())) {
                throw new LoginException("验证码错误！");
            }
        }
        if (username == null || username.equals("")) {
            throw new LoginException("用户名不能为空！");
        }

        if (rawPassword == null || rawPassword.equals("")) {
            throw new LoginException("密码不能为空！");
        }

        if (clientCode == null) {
            throw new LoginException("客户端code不能为空！");
        }

        //查询用户是否存在
        Account userDetails = (Account) userService.loadUserByUsername(username);

        if (!userDetails.isEnabled()) {
            throw new DisabledException("该账户已被禁用，请联系管理员");

        }
        if (userDetails.getLockedlag() == 2) {
            if (userDetails.getUnlockTime().getTime() > new Date().getTime()) {
                throw new LockedException("该账号已被锁定 解锁还需 " + ((userDetails.getUnlockTime().getTime() - new Date().getTime()) / 1000 / 60) + " 分钟！");
            } else {
                ResponseData unlock = accountService.unlock(userDetails.getId());
                if (unlock.getCode() != 200) {
                    throw new LockedException(unlock.getData().toString());
                }
            }

        }
        if (!userDetails.isAccountNonExpired()) {
            throw new AccountExpiredException("该账号已过期，请联系管理员");

        }
        if (!userDetails.isCredentialsNonExpired()) {
            throw new CredentialsExpiredException("该账户的登录凭证已过期，请重新登录");
        }

        //验证密码
        if (!BCrypt.checkpw(rawPassword, userDetails.getPassword())) {
            ResponseData locking = accountService.locking(userDetails.getId(), 1);
            throw new BadCredentialsException(locking.getData().toString());
        }

        if (userDetails.getLasting() != null && userDetails.getLasting().size() > 0) {
            List<AccountClient> client = userDetails.getLasting().stream().filter(item -> item.getClientCode() != null && item.getClientCode().equals(clientCode)).collect(Collectors.toList());
            if (client.size() == 0) {
                throw new LoginException("当前所登录的平台没有开通，请联系管理员开通！");
            }
            AccountClient accountClient = userDetails.getLasting().get(0);
            if (accountClient.getPersistentLogin() == 2) {
                QueryWrapper<LastingLogin> lastingLoginQueryWrapper = new QueryWrapper<>();
                lastingLoginQueryWrapper.eq("client_code", clientCode).eq("account_id", userDetails.getId());
                LastingLogin lastingLogin = lastingLoginService.getBaseMapper().selectOne(lastingLoginQueryWrapper);
                if (lastingLogin == null) {
                    LastingLogin newLastingLogin = new LastingLogin();
                    newLastingLogin.setAccountId(userDetails.getId());
                    newLastingLogin.setUsername(userDetails.getUsername());
                    newLastingLogin.setLastUsed(new Date());
                    newLastingLogin.setClientCode(clientCode);
                    newLastingLogin.setClientId(accountClient.getId());
                    lastingLoginService.save(newLastingLogin);
                } else {
                    lastingLogin.setLastUsed(new Date());
                    lastingLoginService.updateById(lastingLogin);
                }
            }
        }
        return new UsernamePasswordAuthenticationToken(userDetails, rawPassword, userDetails.getAuthorities());
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
    }

//    @Override
//    public boolean supports(Class<?> authentication) {
//        return authentication.equals(UsernamePasswordAuthenticationToken.class);
//    }

    private JSONObject loginInfo(HttpServletRequest request) {
        StringBuilder responseStrBuilder = null;
        try {
            BufferedReader streamReader = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
            responseStrBuilder = new StringBuilder();
            String inputStr;
            while ((inputStr = streamReader.readLine()) != null) {
                responseStrBuilder.append(inputStr);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        if (responseStrBuilder != null) {
            return JSONObject.parseObject(responseStrBuilder.toString());
        }
        return null;
    }


}
